package com.example.springsecurity01.config;

import com.example.springsecurity01.filter.AfterLoginFilter;
import com.example.springsecurity01.filter.AtLoginFilter;
import com.example.springsecurity01.filter.BeforeLoginFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.xml.ws.WebEndpoint;

/**
 * SpringSecurity配置
 *
 * @author lzh
 * @date 2019/9/16 - 8:58
 * 1.@Configuration：注解这是一个配置类
 * 2.@EnableWebSecurity：注解开启Spring Security的功能
 * 3.WebSecurityConfigurerAdapter：继承WebSecurityConfigurerAdapter，并重写它的方法来设置一些web安全的细节
 * 4.configure(AuthenticationManagerBuilder auth)：在内存中创建了用户admin/user，密码为123456
 *
 *
 *  想要开启Spring方法级安全，你需要在已经添加了@Configuration注解的类上再添加@EnableGlobalMethodSecurity注解：
 *
 * （1）prePostEnabled :决定Spring Security的前注解是否可用 [@PreAuthorize,@PostAuthorize,..]
 *
 * （2）secureEnabled : 决定是否Spring Security的保障注解 [@Secured] 是否可用。
 *
 * （3）jsr250Enabled ：决定 JSR-250 annotations 注解[@RolesAllowed..] 是否可用。
 *
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() // 定义哪些URL需要被保护、哪些不需要被保护

                .antMatchers("/login").permitAll()// 设置白名单(所有人都可以访问登录页面)
                .antMatchers("/hello").permitAll()
                .anyRequest().authenticated()  // 任何请求,登录后可以访问
                .and()
                .formLogin()
                .loginPage("/login");


        /**
         * 怎么在Spring Security中的Filter指定位置加入自定义的Filter呐？Spring Security的HttpSecurity为此提供了三个常用方法来配置：
         *
         * （1）addFilterBefore(Filter filter, Class<? extends Filter>beforeFilter)
         *
         * 在 beforeFilter 之前添加 filter
         *
         * （2）addFilterAfter(Filter filter, Class<? extends Filter>afterFilter)
         *
         * 在 afterFilter 之后添加 filter
         *
         * （3）addFilterAt(Filter filter, Class<? extends Filter> atFilter)
         *
         * 在 atFilter 相同位置添加 filter， 此 filter 不覆盖 filter
         */
        http.addFilterBefore(new BeforeLoginFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterAfter(new AfterLoginFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterAt(new AtLoginFilter(), UsernamePasswordAuthenticationFilter.class);

    }





//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        /**
//         * 配置为从内存中进行加载认证信息
//         *  这里配置了两个用户 admin和user
//         *
//         *  Bcrypt： bcrypt是一种跨平台的文件加密工具。bcrypt 使用的是布鲁斯·施内尔在1993年发布的 Blowfish 加密算法。
//         *  由它加密的文件可在所有支持的操作系统和处理器上进行转移。它的口令必须是8至56个字符，并将在内部被转化为448位的密钥
//         */
//        auth.inMemoryAuthentication()
//                .withUser("admin")
//                .password(passwordEncoder().encode("admin"))
//                .roles("admin");
//
//        auth.inMemoryAuthentication()
//                .withUser("user")
//                .password(passwordEncoder().encode("123456"))
//                .roles("normal");
//    }
}
